package com.tedu.api.io;

import org.junit.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * final与finally区别：【考试原题】
 * final 修饰 不可改变类 修饰属性不可改变值【常量】 | 修饰方法 方法不可以重写， 可以重载
 * finally 处理异常块：关闭流
 *
 *
 */

/**
 * 标准IO流--目的：数据传输  输出文本，图片
 * java定义一套标准流-->数据传输-->
 * 标准流规则①：方向划分  输入流和输出流
 *          输入流：读入-->文件-->相对于程序-->文件往程序走
 *          InputStream（抽象类：定义所有读的写法）【学习：子实现类】
 *          输出流：写出-->文件-->相对于程序-->程序写出
 *          OutputStream（抽象类：定义所有写的写法）【学习：子实现类】

 *         ②：功能划分
 *         低级流【节点流】：是建立在程序与数据源之间的”管道“
 *                  功能：负责搬运的数据流，输入流于输出流都有自己的低级流
 *                  特点：一个字节一个字节读或者写的方法
 *         FileOutputSteam 低级流继承InputSteam---文件传输流：写
 *         FileInputSteam 低级流继承OutputSteam---文件传输流：读
 *         高级流【处理流】：不能直接创建对象，不能独立存在
 *                  功能：专门处理低级流以及其他的高级流的流
 *                  特点：搬运数据时，实现具体功能，效率提高流
 * ---总结：输入流和输出流，具备功能：低级流和高级流
 * 实际使用：明确使用具体流，每个流都有自己的功能
 *
 */
public class IOAPI {
    /**
     *                                文件输入流
     *                      低级流
     * 标准流   方向   功能              文件输出流：FileOutputSteam
     *                      高级流
     * 需求：写一个文件fos.txt
     *
     * FileOutputStream 构造器使用
     * new FileOutputStream（“路径+文件全称”）
     * new FileOutputStream（“路径+文件全称”，boolean append）
     * 写出文件的同时实现追加效果，第二个参数：true 追加
     *                                  false 不追加
     * new FileOutputSteam(File,file,boolean append)
     */
    @Test
    public void testFOS() {
        //RandomAccessFile raf=new RandomAccessFile("fos.txt","rw");
        //低级流--文件输出流对象---从程序中写出”文件：数据“
        FileOutputStream fos= null;
        try {
            fos = null;
            fos=new FileOutputStream("fos.txt",true);
            String say="金珉奎";
            //字符串由字符数组构成--数组的功能--getBytes（）转换为字节数组
            //输出流--写功能:write（byte[] b）写出字节数组
            fos.write(say.getBytes("UTF8"));
            //必须关闭流--目的：节省内存开销
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos!=null)
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 文件输入流：读入操作
     * FileInputStream 文件输出流
     * read（）返回一个读取一个字节--效率低
     * read（字节数组byte[] b）返回一个“指定字节数组：空间大小”的读取--效率高
     * 需求:读入fas.txt
     */
    @Test
    public void testFIS(){
        //创建文件输入流--读入：fos.txt
        FileInputStream fis=null;
        try {
            fis=new FileInputStream("fos.txt");
            //读入效率高:创建字节数组-指定空间为：10KB
            byte[] data=new byte[1024*10];
            //读入操作：read（字节数组）| 一10KB读入数据
            int len=fis.read(data);
            //写出：文本--字符串--针对流操作，提供构造器
            //                 文件按照“指定字节数组空间”写入程序中
            //                 从0开始写入程序，写入到-1结束
            //                 len：十进制转换为二进制，写入，不等于-1，一直写入
            //一次性将给定数据按照字节数组指定空间大小，写出成字符串
            String str=new String(data,0,len);
            System.out.println("打印Fos.txt文件："+str);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            }catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                if(fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 需求：利用标准流实现视频复制粘贴
     */
    @Test
    public void testCV() {
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            //1.从“复制文件.mp4”  操作--读入

            fis=new FileInputStream("复制视频.mp4");
            //2.创建新文件“新文件.mp4" 粘贴 操作--写出
            fos=new FileOutputStream("新文件.mp4");
            //3.保存每次读取的数据【字节量--int】
            int len=-1;
            //4.一直从“复制文件.mp4"进程读入操作，不等于-1 一直读
            while ((len=fis.read()) !=-1) {
                //4.1同时 写出“新文件.mp4"
                fos.write(len);
            }
            //5.关闭流   ---测：效率低--正常播放

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(fos!=null)
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
    /**
     * 需求：利用标准流实现视频复制粘贴--效率低
     *                             效率高-->空间执行下午：自定 100KB
     * 【高级流】BufferedInputSteam 缓冲输入流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *         BufferedOutputSteam 缓冲输出流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     * 高级流使用方法：①处理低级流，套在低级流上
     *              写法：new 高级流（传入低级流引用）
     *              ②直接使用高级流的方法
     *              ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() {
       //创建低级流：读入“复制视频.mp4"
        FileInputStream fis=null;
        BufferedInputStream bis=null;
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        try {
            fis=new FileInputStream("复制视频.mp4");
            //创建高级流：套在低级流上【自带缓冲区：字节数组】
            bis=new BufferedInputStream(fis);
            //创建低级流：写出“高效视频.mp4"
            fos=new FileOutputStream("高效视频.mp4");
            //创建高级流：套在低级流上【自带缓冲区：字节数组】
            bos=new BufferedOutputStream(fos);
            //3.保护数据
            int len=-1;
            //4.高级流--低级流方法一致--read（）读取内嵌缓冲区【字节数组】
            //一直从“复制视频.mp4"读取数据 ，不等于-1，一直读
            //(len= bis.read())!=-1
            long start=System.currentTimeMillis();
            while ((len=bis.read())!=-1){
                bos.write(len);
            }
            long end=System.currentTimeMillis();
            System.out.println("缓冲区【自带缓冲区】："+(end-start)+"毫秒数");
            //关闭流---低级流与高级流：都关---.高级流间接关闭低级流
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        }if (bis!=null)
            try {
                bis.close();//高级流--缓冲输入流
            } catch (IOException e) {
                e.printStackTrace();
            }if (bos!=null)
            try {
                bos.close();//高级流--缓冲输出流
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    /**
     * 高级流--缓冲流【内嵌缓冲区】
     * BufferedOutputSteam  缓冲输出流
     *
     * 需求：通过缓冲输出流实现从程序写出文件：bos.txt，写出内容
     */
    @Test
    public void testBOS() throws IOException {
        //1.创建低级流-->bos.txt
        FileOutputStream fos=new FileOutputStream("bos.txt");
        //2.创建高级流-->缓冲区：字节数组--合理
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        //3.写出文本内容
        String str="金珉奎地球球草";
        //4.写出到bos.txt文件中
        bos.write(str.getBytes());
        //5.将缓冲区数据一次性写出 flush（）
        //bos.flush();
        bos.close();//关闭流--一定把缓冲区数据 全部写出
    }
    /**
     *
     *
     */
    @Test
    public void testBOSIO(){
        //1.置空流--提示所有流作用域：使用范围
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        //2.捕获流异常并且捕获
        try {
            fos = new FileOutputStream("bos.txt");//低级流
            bos = new BufferedOutputStream(fos);//高级流：缓冲区
            bos.write("独一无二".getBytes());
            bos.flush();
        }catch (FileNotFoundException e){//IO流 “小”异常
            e.printStackTrace();
        } catch (IOException e) { //IO流 “中”异常：小异常父类
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace(); //“大” 异常 Exception
        } finally {//一定执行代码块
            //3.关闭流--高级流--释放资源
            //判断：高级流一定是不为null，关闭
            if (bos!=null)
                try{
                    bos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
        }
    }
}
